{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\ftech Symbol;\f2\fmodern Ohlfs;}
\margl40
\margr40
{\colortbl;\red0\green0\blue0;}
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i0\ulnone\fs24\fc0\cf0 //ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//
\i 	
\b FILENAME
\b0 :	
\b\i0 eTDoc.m\

\b0 //
\i 	
\b SUMMARY
\b0 :	
\b\i0 Implementation of the abstract document controller.
\b0 \
//	
\b\i SUPERCLASS
\b0 :
\i0 	
\b Object:eTDoc
\b0 \
//	
\b\i PROTOCOLS
\b0 :
\i0 	
\b Uses <DocNotification>
\b0 \
//	
\b\i INTERFACE
\b0 :
\i0 	
\b None
\b0 \
//	
\b\i AUTHOR
\b0 :		
\b\i0 Rohit Khare
\b0 \
//	
\b\i COPYRIGHT
\b0 :	
\f1\i0 с
\f0\b 1993,94 California Institure of Technology, eText Project\

\b0 //ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b\i Implementation Comments
\b0\i0 \
//		Keep a careful eye on the construction/destruction process!\
//	Also watch for the inanities of how file-reading is covered between 
\i etDoc
\i0 \
//	and 
\i eTAppUI
\i0 .\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b\i HISTORY
\b0\i0 \
//	10/06/94:	
\b Revamped for eText5.
\i \

\b0\i0 //	07/20/94:	
\b Added LaTeX as per Tim Berners-Lee's sed script; cleanup.
\b0 \
//	06/17/94	
\b Added writeHTMD isBold,isItalic,isFixedPitch. By RK and TRZ.
\b0 \
//	01/14/94:	
\b Completely revised for version 4.0
\b0 \
//	09/11/93:	
\b Created (un)registerForDocNotification. <DocNotification>
\b0 \
//	09/09/93:	
\b Added support for the docID member.
\b0 \
//	08/22/93:	
\b Moved "Accessor Methods" to eTDoc
\b0 \
//	08/21/93:	
\b Created.
\b0 \
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b Imported Interfaces
\b0 \
//\
	#import "
\b eTDoc.h
\b0 "\
	#import "
\b eTDocInfoUI.h
\b0 "\
	#import "
\b eTDocUI.h
\b0 "\
\

\i @implementation eTDoc\

\i0 \
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
// 	
\b Class Management
\b0 \
//\
- 
\b initForDocInfo
\b0 :(
\b eTDocInfo
\b0  *) newDocInfo \{\
	
\b Panel
\b0 	*
\b oPanel
\b0 ;\
	
\b NXSelPt
\b0  
\b b
\b0 ,
\b e
\b0 ;\
\
    [super init];\
\
	//	
\i PHASE I: Initialize the internal model
\i0 \
	
\b theDocInfo
\b0  = 
\b newDocInfo
\b0 ;\
	
\b notificationList
\b0  = [[
\b List
\b0  alloc] 
\b init
\b0 ];\
	[self 
\b registerNotification
\b0 :
\b navigator
\b0 ];\
	
\b componentTable
\b0  = [[
\b HashTable
\b0  alloc] 
\b initKeyDesc
\b0 :"
\b %
\b0 "];\
	
\b undoManager
\b0  = [[
\b UndoManager
\b0  alloc] 
\b init
\b0 ];\
	[
\b undoManager
\b0  
\b setLevelsOfUndo
\b0 :
\b 50
\b0 ]; // 
\i this should be an NXDefault
\i0 \
	[
\b theDocInfo
\b0  
\b setDoc
\b0 :
\b self
\b0 ];\
	
\b selectedObj
\b0  = 
\b theDocInfo
\b0 ;\
	if (*[theDocInfo 
\b agent
\b0 ])\
		[self 
\b attachAgent
\b0 :[[[
\b etApp
\b0  
\b agentByName
\b0 :[theDocInfo 
\b agent
\b0 ]]\
									
\b alloc
\b0 ] 
\b init
\b0 :theDocInfo]];\
	else 
\b theAgent
\b0  = nil;\
	[
\b undoManager
\b0  
\b disableUndoRegistration
\b0 ];\
\
	//	
\i PHASE II: Construct the UI
\i0 \
	
\b oPanel
\b0  = 
\b NXGetAlertPanel
\b0 ("
\b eTDoc
\b0 ",\
					"
\b Opening the document titled %s
\b0 .",\
					NULL, NULL, NULL, [
\b theDocInfo
\b0  
\b docTitle
\b0 ]);\
	[oPanel setFloatingPanel:NO];\
	[oPanel setHideOnDeactivate:YES];\
	[oPanel 
\b orderFront
\b0 :self];\
	NXPing();\
	
\b docUI
\b0  = [[[
\b eTDocUI
\b0  alloc] 
\b init
\b0 ] 
\b setDoc
\b0 :
\b self
\b0 ];\
\
	// 
\i PHASE III: Opening The Files
\i0 \
	[self 
\b openFrom
\b0 :[theDocInfo 
\b docPath
\b0 ]];\
\
	// 
\i PHASE IV: Notifications
\i0 \
	// 
\i There's a little fudging between 
\i0 eTDoc
\i  and 
\i0 eTDocUI
\i  here because the
\i0 \
	// 
\i selection can get screwed up by the broadcast
\i0 .\
	[[docUI window] 
\b disableDisplay
\b0 ];\
	[[docUI eTextObj] 
\b getSel
\b0 :&b :&e];\
	\{	int count;\
		count = [
\b notificationList
\b0  
\b count
\b0 ];\
		while (count--)\
			if([[notificationList objectAt:count]\
				respondsTo:@selector(
\b docWillOpen:
\b0 )])\
				[[notificationList objectAt:count] 
\b docWillOpen
\b0 :
\b self
\b0 ];\
	\}\
	[[docUI eTextObj] 
\b setSel
\b0 :b.cp :e.cp];\
	[[docUI eTextObj] 
\b scrollSelToVisible
\b0 ];\
	[[docUI window] 
\b setDocEdited
\b0 :
\b NO
\b0 ];\
	[[docUI window] 
\b reenableDisplay
\b0 ];\
	[
\b undoManager
\b0  
\b reenableUndoRegistration
\b0 ];\
	if (oPanel) \{\
		[oPanel 
\b orderOut
\b0 :self];\
		
\b NXFreeAlertPanel
\b0 (oPanel);\
	\}\
	return self;\
\}\
- 
\b free
\b0 \
\{\
	[
\b undoManager
\b0  
\b emptyUndoManager
\b0 ];\
	undoManager = [
\b undoManager
\b0  free];\
	[
\b inspector
\b0  
\b inspect
\b0 :
\b nil
\b0 ]; //
\i invalidate would have gone back to the window.
\i0 \
	docUI = [
\b docUI
\b0  free];\
	[
\b theDocInfo
\b0  
\b setDoc
\b0 :
\b nil
\b0 ];\
	notificationList = [
\b notificationList
\b0  free];\
	return [super free];\
\}\
\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
// 	
\b Document Management (by path)
\b0 \
//\
- 
\b openFrom
\b0 :(const char *)thePath \{\
	if (
\b !access
\b0 (
\b thePath
\b0 , 
\b F_OK
\b0 )) \{ 	//
\i  OK, we have a diskfile
\i0 \
		char	tmp[MAXPATHLEN];\
		\
		sprintf(
\b tmp
\b0 , "
\b %s/TXT.rtf
\b0 ", 
\b thePath
\b0 );\
		if (
\b !access
\b0 (tmp, 
\b R_OK
\b0 )) \{\
			// 
\i CASE I: We have ETFD/RTFD
\i0 \
			[[docUI 
\b eTextObj
\b0 ] 
\b readETFfromPath
\b0 :
\b tmp
\b0 ];\
		\} else \{\
			// 
\i CASE II: We have Text/RTF
\i0 \

\b 			NXStream
\b0  *
\b memstream
\b0  = NXMapFile(
\b thePath
\b0 , NX_READONLY);\
			if (memstream) \{\
				char magic[8];\
				\

\b 				NXRead
\b0 (memstream, 
\b magic
\b0 ,6);\
				NXSeek(memstream, 0, NX_FROMSTART);\
				if (!
\b strncmp
\b0 (magic,"
\b \{\\\\rtf0
\b0 ",6)) \{\
					[[docUI 
\b eTextObj
\b0 ] 
\b readRichText
\b0 :memstream];\
				\} else \{\
					[[docUI 
\b eTextObj
\b0 ] 
\b readText
\b0 :memstream];\
				\}\
				
\b NXCloseMemory
\b0 (memstream, NX_FREEBUFFER);\
			\}\
		\}\
		[[docUI 
\b eTextObj
\b0 ] 
\b setEditable
\b0 :(![theDocInfo 
\b readOnly
\b0 ])];\
	\}\
	return self;\
\}\
- 
\b saveTo
\b0 :(const char*)thePath 
\b inFormat
\b0 :(
\b int
\b0 )fmt 
\b changePath
\b0 :(
\b BOOL
\b0 ) changeIt \{\
	id			
\b sPanel
\b0 ;\
	char*
\b desc[6]
\b0 =\{
\b ETFD_DESC
\b0 ,
\b\fc1\cf1 ASCII_DESC
\b0\fc0\cf0 ,
\b\fc1\cf1 C_DESC
\b0\fc0\cf0 ,
\b\fc1\cf1 TeXD_DESC
\b0 ,
\b HTMD_DESC
\b0 ,
\b RTF_DESC
\b0\fc0\cf0 \};\
\
	[[docUI 
\b window
\b0 ] 
\b disableDisplay
\b0 ];\
	[inspector 
\b freeze
\b0 ];\
	\
	// 
\i PHASE I: Notifications
\i0 \
	\{	int count;\
		count = [notificationList count];\
		while (count--)\
			if([[notificationList objectAt:count]\
				
\b respondsTo
\b0 :@selector(
\b docWillWrite:
\b0 )])\
				[[
\b notificationList
\b0  objectAt:count] 
\b docWillWrite
\b0 :
\b self
\b0 ];\
	\}\
	
\b sPanel
\b0  = 
\b NXGetAlertPanel
\b0 ("
\b eTDoc
\b0 ",\
				"
\b Saving document to \\"%s\\" in %s Format.
\b0 ",\
				NULL, NULL, NULL, 
\b thePath
\b0 , 
\b desc
\b0 [fmt]);\
	[sPanel setFloatingPanel:NO];\
	[sPanel setHideOnDeactivate:YES];\
	[sPanel 
\b orderFront
\b0 :self];\
	NXPing();\
	// 
\i PHASE II: Writing the files
\i0 \
	
\b switch
\b0 (
\b fmt
\b0 )\{\
		case 
\b ETFD_FMT
\b0 : 	[self 
\b saveETFD
\b0 :thePath 
\b changePath
\b0 :changeIt]; break;\
		case 
\b ASCII_FMT
\b0 : 	[self 
\b saveASCII
\b0 :thePath]; break;\
		case 
\b C_FMT
\b0 : 		[self 
\b saveC
\b0 :thePath]; break;\
		case 
\b TeXD_FMT
\b0 : 	[self 
\b saveLaTeX
\b0 :thePath]; break;\
		case 
\b HTMD_FMT
\b0 :		[self 
\b saveHTMD
\b0 :thePath]; break;\
		case 
\b RTF_FMT
\b0 :		[self 
\b saveRTF
\b0 :thePath]; break;\
    \}\
	if (sPanel) \{\
		[sPanel 
\b orderOut
\b0 :self];\
		
\b NXFreeAlertPanel
\b0 (
\b sPanel
\b0 );\
	\}\
	// 
\i PHASE III: Notifications
\i0 \
	\{	int count;\
		count = [notificationList count];\
		while (count--)\
			if([[notificationList objectAt:count]\
				
\b respondsTo
\b0 :@selector(
\b docDidWrite:
\b0 )])\
				[[
\b notificationList
\b0  objectAt:count] 
\b docDidWrite
\b0 :
\b self
\b0 ];\
	\}\
	[inspector 
\b thaw
\b0 ];\
	[[[docUI 
\b window
\b0 ]  
\b reenableDisplay
\b0 ] 
\b display
\b0 ];\
	return self;\
\}\
- 
\b close
\b0 :sender 
\b allowCancel
\b0 :(
\b BOOL
\b0 )cancellable \{\
	return [
\b docUI
\b0  
\b close
\b0 :sender 
\b allowCancel
\b0 :cancellable];\}\
- 
\b save
\b0 :sender \{\
	return [
\b docUI
\b0  
\b save
\b0 :sender];\}\
\
- 
\b saveASCII
\b0 :(const char *) thePath \{\
	[[docUI 
\b eTextObj
\b0 ] 
\b writeASCIItoPath
\b0 :thePath];\
	return self;\}\
- 
\b saveC
\b0 :(const char *) thePath \{\
	[[docUI 
\b eTextObj
\b0 ] 
\b writeCtoPath
\b0 :thePath];\
	return self;\}\
- 
\b saveRTF
\b0 :(const char *) thePath \{\
	[[docUI 
\b eTextObj
\b0 ] 
\b writeRTFtoPath
\b0 :thePath];\
	return self;\}\
- 
\b saveLaTeX
\b0 :(const char *) thePath\
\{\
	char 				
\b LaTeXfile
\b0 [MAXPATHLEN];\
	int					i;\
    struct stat 		st;\
	DIR 				*dirp;\
	struct direct 		*dp;\
	NXStream 			*
\b s
\b0 ;\
	
\b taggingInfo
\b0   		
\b tags
\b0 [8];\
\
	// 	
\i PHASE I: Prepare thePath
\i0 		\
	if (
\b stat
\b0 (
\b thePath
\b0 , &st) || (((st.
\b st_mode
\b0  & S_IFMT) 
\b !=
\b0  
\b S_IFDIR
\b0 )))\{\
		
\b removeFile
\b0 (
\b thePath
\b0 );\
		if (
\b mkdir
\b0 (
\b thePath
\b0 , 0777)) \{\
			NXLogError("
\b Could not mkdir(
\b0 \\"%s\\"
\b )
\b0 ", 
\b thePath
\b0 );\
			perror("eText5");\
			
\b NXBeep
\b0 ();\
			return nil;\
		\}\
	\}\
	[
\b componentTable
\b0  
\b empty
\b0 ];\
\
	//	
\i PHASE II: Prepare taggingInfo
\i0 \
	i=0;	// 
\i is incremented to compact out undefined tagging fonts
\i0 \
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H1
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b \\\\part\{
\b0 "); // 
\i use \{book\} with \\chapter
\i0 \
	tags[i].
\b end
\b0  = NXUniqueString("
\b \}\\n
\b0 ");\
	if (tags[i].font) i++;\
\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H2
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b \\\\section\{
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b \}\\n
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H3
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b \\\\subsection\{
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b \}\\n
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H4
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b \\\\subsubsection\{
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b \}\\n
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H5
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b \\\\paragraph\{
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b \}\\n
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H6
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b \\\\subparagraph\{
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b \}\\n
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b QT
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b \\\\begin\{quote\}
\b0 \\n");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b \\\\end\{quote\}
\b0 \\n");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  = 
\b NULL
\b0 ; tags[i].
\b start
\b0  = tags[i].
\b end
\b0  = 
\b NULL
\b0 ;\
	\
	// 	
\i PHASE III: Collect Annotations\

\i0 	sprintf(
\b LaTeXfile
\b0 , "
\b %s/%s.tex
\b0 ", 
\b thePath
\b0 , [theDocInfo 
\b docTitle
\b0 ]);\
	
\b s
\b0  = 
\b NXOpenMemory
\b0 (NULL, 0, NX_WRITEONLY);\
	
\b NXPrintf
\b0 (s,"
\b \\\\documentstyle[times,epsf]\{article\}\\n\\\\begin\{document\}\\n
\b0 ");\
	[
\b theDocInfo
\b0  
\b writeLaTeXHeader
\b0 :s];\
	[[docUI 
\b eTextObj
\b0 ] 
\b writeLaTeX
\b0 :s 
\b withTags
\b0 :
\b tags
\b0 ];\
	
\b NXPrintf
\b0 (s,"
\b \\n\\\\end\{document\}\\n
\b0 ");\
	
\b NXSaveToFile
\b0 (s, 
\b LaTeXfile
\b0 );\
	
\b NXCloseMemory
\b0 (s, 
\b NX_FREEBUFFER
\b0 );\
	\
	// 
\i PHASE IV: Notifications
\i0 \
	\{	int count;\
		count = [
\b notificationList
\b0  count];\
		while (count--)\
			if([[notificationList objectAt:count]\
				
\b respondsTo
\b0 :@selector(
\b writeComponentToPath:inFormat:
\b0 )])\
				[[notificationList objectAt:count]\
				
\b writeComponentToPath
\b0 :
\b thePath
\b0  
\b inFormat
\b0 :
\b TeXD_FMT
\b0 ];\
	\}\
\
	//	
\i PHASE V: Garbage Collection
\i0 \
	// 
\i Iterate through the directory, deleting bastard objects
\i0 \
	[self 
\b registerComponent
\b0 :NXUniqueString(
\b rindex
\b0 (
\b LaTeXfile
\b0 , '
\b /
\b0 ')
\b +1
\b0 )];\
	[self 
\b registerComponent
\b0 :NXUniqueString("
\b .
\b0 ")];\
	[self 
\b registerComponent
\b0 :NXUniqueString("
\b ..
\b0 ")];\
	dirp = 
\b opendir
\b0 (
\b thePath
\b0 );\
	dp = readdir(dirp); \
	while (dp != NULL) \{\
		if (![
\b componentTable
\b0  
\b isKey
\b0 :NXUniqueString(
\b dp->d_name
\b0 )]) \{\
			sprintf(LaTeXfile, "
\b %s/%s
\b0 ", 
\b thePath
\b0 , 
\b dp->d_name
\b0 );\
			
\b removeFile
\b0 (LaTeXfile);\
    	\}\
		dp = readdir(dirp);\
	\}\
	closedir(dirp);\
	[
\b componentTable
\b0  
\b empty
\b0 ];\
	return self;\
\}\
- 
\b saveHTMD
\b0 :(const char *) thePath\
\{\
	char 				
\b HTMLfile
\b0 [MAXPATHLEN];\
	int					i;\
    struct stat 		st;\
	DIR 				*dirp;\
	struct direct 		*dp;\
	NXStream 			*
\b s
\b0 ;\
	taggingInfo  		
\b tags
\b0 [8];\
\
	// 	
\i PHASE I: Prepare thePath
\i0 		\
	if (
\b stat
\b0 (
\b thePath
\b0 , &st) || (((st.
\b st_mode
\b0  & S_IFMT) 
\b !=
\b0  
\b S_IFDIR
\b0 )))\{\
		
\b removeFile
\b0 (
\b thePath
\b0 );\
		if (
\b mkdir
\b0 (
\b thePath
\b0 , 0777)) \{\
			NXLogError("
\b Could not mkdir(
\b0 \\"%s\\"
\b )
\b0 ", 
\b thePath
\b0 );\
			perror("eText5");\
			
\b NXBeep
\b0 ();\
			return nil;\
		\}\
	\}\
	[
\b componentTable
\b0  
\b empty
\b0 ];\
\
	//	
\i PHASE II: Prepare taggingInfo
\i0 \
	i=0;	// 
\i is incremented to compact out undefined tagging fonts
\i0 \
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H1
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b <H1>
\b0 "); // 
\i use \{book\} with \\chapter
\i0 \
	tags[i].
\b end
\b0  = NXUniqueString("
\b </H1>
\b0 ");\
	if (tags[i].font) i++;\
\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H2
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b <H2>
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b </H2>
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H3
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b <H3>
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b </H3>
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H4
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b <H4>
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b </H4>
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H5
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b <H5>
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b </H5>
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b H6
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b <H6>
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b </H6>
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  =[theDocInfo 
\b tagFont
\b0 :
\b QT
\b0 ];\
	tags[i].
\b start
\b0  = NXUniqueString("
\b <BLOCKQUOTE>
\b0 ");\
	tags[i].
\b end
\b0  = NXUniqueString("
\b </BLOCKQUOTE>
\b0 ");\
	if (tags[i].font) i++;\
	\
	tags[i].
\b font
\b0  = 
\b NULL
\b0 ; tags[i].
\b start
\b0  = tags[i].
\b end
\b0  = 
\b NULL
\b0 ;\
	\
	// 	
\i PHASE III: Collect Annotations\

\i0 	sprintf(
\b HTMLfile
\b0 , "
\b %s/
\b0 "
\b HTML_INDEX
\b0 , 
\b thePath
\b0 );\
	
\b s
\b0  = 
\b NXOpenMemory
\b0 (NULL, 0, NX_WRITEONLY);\
	NXPrintf(s,"
\b <HTML>\\n
\b0 ");\
	[theDocInfo 
\b writeHTMLHeader
\b0 :s];\
	NXPrintf(s,"
\b \\n<BODY>\\n
\b0 ");\
	[[docUI 
\b eTextObj
\b0 ] 
\b writeHTML
\b0 :
\b s
\b0  
\b withTags
\b0 :
\b tags
\b0 ];\
	[theDocInfo 
\b writeHTMLTrailer
\b0 :
\b s
\b0 ];\
	NXPrintf(s,"
\b \\n</BODY>\\n</HTML>\\n
\b0 ");\
	
\b NXSaveToFile
\b0 (s, 
\b HTMLfile
\b0 );\
	
\b NXCloseMemory
\b0 (s, 
\b NX_FREEBUFFER
\b0 );\
	\
	// 
\i PHASE IV: Notifications
\i0 \
	\{	int count;\
		count = [
\b notificationList
\b0  count];\
		while (count--)\
			if([[notificationList objectAt:count]\
				
\b respondsTo
\b0 :@selector(
\b writeComponentToPath:inFormat:
\b0 )])\
				[[notificationList objectAt:count]\
				
\b writeComponentToPath
\b0 :
\b thePath
\b0  
\b inFormat
\b0 :
\b HTMD_FMT
\b0 ];\
	\}\
\
	//	
\i PHASE V: Garbage Collection
\i0 \
	// 
\i Iterate through the directory, deleting bastard objects
\i0 \
	[self 
\b registerComponent
\b0 :NXUniqueString(
\b HTML_INDEX
\b0 )];\
	[self 
\b registerComponent
\b0 :NXUniqueString("
\b .
\b0 ")];\
	[self 
\b registerComponent
\b0 :NXUniqueString("
\b ..
\b0 ")];\
	dirp = 
\b opendir
\b0 (
\b thePath
\b0 );\
	dp = readdir(dirp); \
	while (dp != NULL) \{\
		if (![
\b componentTable
\b0  
\b isKey
\b0 :NXUniqueString(
\b dp->d_name
\b0 )]) \{\
			sprintf(HTMLfile, "
\b %s/%s
\b0 ", 
\b thePath
\b0 , 
\b dp->d_name
\b0 );\
			
\b removeFile
\b0 (HTMLfile);\
    	\}\
		dp = readdir(dirp);\
	\}\
	closedir(dirp);\
	[
\b componentTable
\b0  
\b empty
\b0 ];\
	return self;\
\}\
- 
\b saveETFD
\b0 :(const char *) thePath 
\b changePath
\b0 :(
\b BOOL
\b0 ) changeIt\
\{\
	NXAtom oldPath;\
	char ETFfile[MAXPATHLEN];\
    struct stat st;\
	DIR *dirp;\
	struct direct *dp;\
\
	// 	
\i PHASE I: Prepare thePath
\i0 		\
	if (
\b stat
\b0 (
\b thePath
\b0 , &st) || (((st.
\b st_mode
\b0  & S_IFMT) 
\b !=
\b0  
\b S_IFDIR
\b0 )))\{\
		
\b removeFile
\b0 (
\b thePath
\b0 );\
		if (
\b mkdir
\b0 (
\b thePath
\b0 , 0777)) \{\
			NXLogError("
\b Could not mkdir(
\b0 \\"%s\\"
\b )
\b0 ", 
\b thePath
\b0 );\
			perror("eText5");\
			
\b NXBeep
\b0 ();\
			return nil;\
		\}\
	\}\
	[
\b componentTable
\b0  
\b empty
\b0 ];\
\
	
\b oldPath
\b0 =[theDocInfo 
\b docPath
\b0 ];\
	[theDocInfo 
\b setDocPath
\b0 :
\b thePath
\b0 ];	// 
\i this confuses saveTo:
\i0 \
\
	// 	
\i PHASE II: Collect Annotations\

\i0 	sprintf(
\b ETFfile
\b0 , "
\b %s/TXT.rtf
\b0 ", 
\b thePath
\b0 );\
	[[docUI 
\b eTextObj
\b0 ] 
\b writeETFtoPath
\b0 :
\b ETFfile
\b0 ];\
	\
	// 
\i PHASE III: Notifications
\i0 \
	\{	int count;\
		count = [
\b notificationList
\b0  count];\
		while (count--)\
			if([[notificationList objectAt:count]\
				
\b respondsTo
\b0 :@selector(
\b writeComponentToPath:inFormat:
\b0 )])\
				[[notificationList objectAt:count]\
				
\b writeComponentToPath
\b0 :
\b thePath
\b0  
\b inFormat
\b0 :
\b ETFD_FMT
\b0 ];\
	\}\
\
	//	
\i PHASE IV: Garbage Collection
\i0 \
	// 
\i Iterate through the directory, deleting bastard objects
\i0 \
	[self 
\b registerComponent
\b0 :NXUniqueString("
\b TXT.rtf
\b0 ")];\
	[self 
\b registerComponent
\b0 :NXUniqueString("
\b .
\b0 ")];\
	[self 
\b registerComponent
\b0 :NXUniqueString("
\b ..
\b0 ")];\
	dirp = 
\b opendir
\b0 (
\b thePath
\b0 );\
	dp = readdir(dirp); \
	while (dp != NULL) \{\
		if (![
\b componentTable
\b0  
\b isKey
\b0 :NXUniqueString(
\b dp->d_name
\b0 )]) \{\
			sprintf(ETFfile, "
\b %s/%s
\b0 ", 
\b thePath
\b0 , 
\b dp->d_name
\b0 );\
			
\b removeFile
\b0 (ETFfile);\
    	\}\
		dp = readdir(dirp);\
	\}\
	closedir(dirp);\
	[
\b componentTable
\b0  
\b empty
\b0 ];\
	if (!
\b changeIt
\b0 ) [
\b theDocInfo
\b0  
\b setDocPath
\b0 :
\b oldPath
\b0 ];\
	return self;\
\}\
\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
// 	
\b <DocNotification> Registration & Callbacks
\b0 \
//\
- 
\b registerNotification
\b0 :theListener \{\
	[notificationList 
\b addObjectIfAbsent
\b0 :theListener]; return self;\}\
- 
\b unregisterNotification
\b0 :theListener \{\
	[notificationList 
\b removeObject
\b0 :theListener]; return self;\}\
- 
\b registerComponent
\b0 :(NXAtom)component \{\
	[componentTable 
\b insertKey
\b0 :NXUniqueString(
\b component
\b0 ) 
\b value
\b0 :
\b nil
\b0 ];\
	return self;\}\
\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
// 	
\b Accessors & API
\b0 \
//\
- (UndoManager *)
\b undoManager 
\b0 \{\
	return 
\b undoManager
\b0 ;\}\
- (eTDocInfo *)
\b docInfo
\b0  \{\
	return 
\b theDocInfo
\b0 ;\}\
- (eTDocUI *)
\b docUI
\b0  \{						// 
\i Private\

\i0 	return 
\b docUI
\b0 ;\}\
	\
- 
\b touch
\b0  \{\
	return [
\b docUI
\b0  
\b touch
\b0 ];\}\
- (
\b BOOL
\b0 ) 
\b needsSaving
\b0  \{\
	return [
\b docUI
\b0  
\b needsSaving
\b0 ];\}\
\
- (
\b BOOL
\b0 ) 
\b acceptsAnnotation
\b0  \{\
	
\b NXSelPt
\b0  
\b a
\b0 ,
\b b
\b0 ;\
	\
	[[docUI 
\b eTextObj
\b0 ] 
\b getSel
\b0 :&
\b a
\b0  :&
\b b
\b0 ];\
	return ((
\b a.cp
\b0  
\b >= 0
\b0 ) && [[docUI 
\b eTextObj
\b0 ] 
\b isEditable
\b0 ]);\}\
- 
\b insertAnnotation
\b0 :theAnnotation \{\
	return [[docUI 
\b eTextObj
\b0 ] 
\b insertAnnotation
\b0 :theAnnotation];\}\
	\
- (
\b BOOL
\b0 ) 
\b acceptsAgent
\b0  \{\
	return 
\b theAgent
\b0  ? 
\b NO
\b0  : 
\b YES
\b0 ;\}\
- 
\b attachAgent
\b0 :newAgent \{\
	if (![
\b newAgent
\b0  
\b conformsTo
\b0 :@protocol(
\b Agent
\b0 )]) return 
\b nil
\b0 ;\
	
\b theAgent
\b0  = 
\b newAgent
\b0 ;\
	[theDocInfo 
\b setAgent
\b0 :NXUniqueString([
\b theAgent
\b0  
\b name
\b0 ])];\
	return [
\b docUI
\b0  
\b attachAgent
\b0 :theAgent];\}\
- 
\b detachAgent
\b0  \{\
	[
\b theDocInfo
\b0  
\b setAgent
\b0 :NXUniqueString("")];\
	[
\b docUI
\b0  
\b detachAgent
\b0 ];\
	
\b theAgent
\b0  = 
\b nil
\b0 ;\
	return self;\
\}\
\
- 
\b selectedObj
\b0  \{\
	return 
\b selectedObj
\b0 ;\}\
- 
\b setSelectedObj
\b0 :it \{\
	selectedObj = 
\b it
\b0 ; \
	return self;\}\
- 
\b makeVisible
\b0  \{\
	[[docUI 
\b window
\b0 ] 
\b makeKeyAndOrderFront
\b0 :self]; \
	return self;\}\
- 
\b inspect
\b0  \{\
	selectedObj = 
\b theDocInfo
\b0 ;\
	return [
\b inspector
\b0  
\b inspect
\b0 :
\b selectedObj
\b0 ];\}\
\

\i @end
}
